using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using Sirenix.OdinInspector;
using UnityEngine.InputSystem;
using UnityEngine.Animations.Rigging;
/// <summary>
/// 作为处理核心， 兼具了流式输入+Trigger输入的功能
/// 只处理, 不管理, 管理需要 Input层和Skill层协商
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(VActState_Loader), typeof(VActSkill_Loader),typeof(VActInput))]

public class VActProcessor : MonoBehaviour
{
    #region 
    //这里是加载设置, 应该由外部类加载, 先放到最基层
    private void LoadSetting()
    {
        if (SFrameworkGate.InEditor && !SFrameworkGate.IsPlaying) return;
        var input = gameObject.UniqueComponent<VActInput>();
        input.Init(this);
        gameObject.UniqueComponent<VActState_Loader>().Init(this, input);
        gameObject.UniqueComponent<VActSkill_Loader>().Init(this, input);
        data = gameObject.UniqueComponent<VActProcessorData>();
        Debug.Log("ActProcessorSettingInit");
    }
    #endregion
    [HideInInspector] public VActProcessorData data;
    public VActMotionVectorMechine mvm;
    [HorizontalGroup("Idle")] public AnimationClip idleClip;
    public VS_AnimationGraph VS_AnimationGraph;
    public VS_EntityGraph VS_EntityGraph;
    public VS_VacancyGraph VS_VacancyGraph;
    public VS_InteractGraph VS_InteractGraph;
    public VS_ControlGraph VS_ControlGraph;
    public VS_AudioGraph VS_AudioGraph;

    private void Start()
    {
        Debug.Log("ActProcessorInit");
        Init();
        LoadSetting();
    }
    public void Init()
    {
        VS_AnimationGraph = new VS_AnimationGraph(gameObject);
        VS_EntityGraph = new VS_EntityGraph(gameObject);
        VS_VacancyGraph = new VS_VacancyGraph(gameObject);
        VS_InteractGraph = new VS_InteractGraph(gameObject);
        VS_ControlGraph = new VS_ControlGraph(gameObject);
        VS_AudioGraph = new VS_AudioGraph(gameObject);
        gloablTable = new List<TimelineClip>();
        mvm = new VActMotionVectorMechine(this, transform);
        processorEnable = true;
        this.SetIdle(idleClip);
    }
    private void OnDisable()
    {
        if (!processorEnable) return;
        processorEnable = false;
        VS_AnimationGraph?.Destroy();
        VS_EntityGraph?.Destroy();
        VS_VacancyGraph?.Destroy();
        VS_InteractGraph?.Destroy();
        VS_ControlGraph?.Destroy();
        VS_AudioGraph?.Destroy();
    }
    [LabelText("核心状态")]
    public bool processorEnable = false;
    public float graphTime;

    private List<TimelineClip> gloablTable;
    private void FixedUpdate()
    {

    }
    [HorizontalGroup("Idle"),Button]
    private void FixPose()
    {
        VS_AnimationGraph.ForceInitGraph();
        0.1f.Delay(VS_AnimationGraph.baseGraph.Stop);
    }
    public VSkillStateGraphBase GetGraph(VSClipType clipType) => clipType switch
    {
        VSClipType.Animation => VS_AnimationGraph,
        VSClipType.Vacancy => VS_VacancyGraph,
        VSClipType.Entity => VS_EntityGraph,
        VSClipType.Interact => VS_InteractGraph,
        VSClipType.Control => VS_ControlGraph,
        VSClipType.Audio => VS_AudioGraph,
        _ => throw new Exception("no Match Graph")
    };
    #region  Extension _ Rig
    [LabelText("启用Rig")][OnValueChanged("OdinCall_SwitchExtension_Rig")] public bool rigEnable;
    [HideInInspector] public VRig rig;
    public void OdinCall_SwitchExtension_Rig()
    {
        if (rigEnable)
        {
            rig = gameObject.UniqueComponent<VRig>();
            rig.Init();
        }
        else
        {
            rig?.OnUnLoad();
            gameObject.RemoveComponent<VRig>();
            rig = null;
        }
    }
    #endregion
    public Dictionary<int, Delegate> onGraphActions = new();
    private void UniqueAddAction<T>(ref T d1, T d2) where T : Delegate
    {
        if (d2 == null)
        {
            d1 = null;
            return;
        }
        var actHash = d2.GetHashCode();
        if (!onGraphActions.ContainsKey(actHash))
        {
            onGraphActions.Add(actHash, d2);
            d1 = (T)Delegate.Combine(d1, d2);
        }
        else
        {
            print("发生重复订阅,已排除");
        }
    }
    /// <summary>
    /// 当AnimationGraph完全回退到idle状态时调用
    /// </summary>
    public Action onTransDefault
    {
        get => VS_AnimationGraph.onTransDefault;
        set => UniqueAddAction(ref VS_AnimationGraph.onTransDefault, value);
    }
    //或者说这个空置域其实只接受某些动作 
    public Action<AnimationClip> onExitAnimation
    {
        get => VS_AnimationGraph.onExitAnimation;
        set => UniqueAddAction(ref VS_AnimationGraph.onExitAnimation, value);
    }
    //多一层enableInput总归是丰富的和好的, 而且顺理成章
    public Action<List<VVacancyActMapper>> onEnterVacancyStringArgs; //就是说整个还得加一层过滤器

    public Action<string, string> onWriteParam
    {
        get => data.onWriteParam;
        set => UniqueAddAction(ref data.onWriteParam, value);
    }

    public Func<bool> onInteract
    {
        get => VS_InteractGraph.onInteract;
        set => UniqueAddAction(ref VS_InteractGraph.onInteract, value);
    }
    public Action<VAct> onEnterNewAct;
    public Action<string> onAskEnterAct;
    public VAct GetCurAct => GetComponent<VActInput>().curDoingAct;//不知道这块层级怎么处理先这么写

    public static Dictionary<Type, Action<VActProcessor, object>> processActions;
}

public static class VActProcessorExtension
{
    //这里根据State中会用到的资源丰富变体行为

    /// <summary>
    /// 手动管理状态
    /// </summary>
    /// <param name="processor"></param>
    /// <param name="animationClip"></param>
    public static void ContinueState(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null)
        {
            processor.VS_AnimationGraph.TransDefault();
        }
        else
        {
            processor.VS_AnimationGraph.ContinueAnimationClip(animationClip);
        }
    }
    //图的支持还得更加完善一些, 人物可以丝滑过渡,但是像这种带了眼睛帧动画的就得直接转 
    public static void TriggerState(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null) processor.VS_AnimationGraph.SetDefault();
        else processor.VS_AnimationGraph.TriggerAnimationClip(animationClip);
    }

    public static void DirectorSetClip(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null)
        {
            processor.VS_AnimationGraph.SetClip(null, 1);
            // processor.DoState();
            // 那么问题就是这里的硬变化怎么做软, 怎么用上过渡
        }
        else
            processor.VS_AnimationGraph.SetClip(animationClip, 1);
    }


    public static void SetIdle(this VActProcessor processor, AnimationClip animationClip = null)
    {
        var Director = processor.GetComponent<PlayableDirector>();
        if (Director != null && Director.enabled) return;
        processor.VS_AnimationGraph.SetDefaultAnimation(animationClip);
        processor.onTransDefault?.Invoke();
    }

    public static void WriteSkillParam(this VActProcessor processor, string key, string value)
    {
        var data = processor.GetComponent<VActProcessorData>();
        data.Write(key, value);
    }

    public static void Continue(this VActProcessor processor, object obj, LoadAssetType assetType)
    {
        switch (assetType)
        {
            case LoadAssetType.AnimationClip:
                processor.ContinueState(obj as AnimationClip);
                break;
            case LoadAssetType.AudioClip:
                processor.VS_AudioGraph.PlayAudio(obj as AudioClip);
                break;
            default:
                return;
        }
    }
    public static void Continue(this VActProcessor processor, string assetName) //这里要求一个name索引的全局资源 管理器
    {
        var unit = assetName.ToAsset();
        processor.Continue(unit.obj, unit.assetType);
    }


    public static void Trigger(this VActProcessor processor)
    {

    }
}